from datetime import datetime
import logging
from core.entities.account_role import AccountWrap
from extensions.ext_database import db
from models.robot.rob_charater import RobCharacter
from models.robot.rob_emoji import RobEmojiPack
from models.robot.rob_timbre import RobTimbre
from services.errors.character import CharacterCreateParamError, CharacterNotExistError
from flask_babel import _

from services.errors.emoji import EmojiPackageNotExistError
from services.errors.timbre import TimbreNotExistError
from services.log_service import LogAction, LogService
class CharacterService:
    @staticmethod
    def get_character_dict_by_id(character_id:str)->dict:
        if character_id:
            character = db.session.get(RobCharacter,character_id)
            if not character:
                raise CharacterNotExistError(character_id)
            return character.to_dict()
        return {}
    
    @staticmethod
    def get_character_list(tenant_id,args:dict)->dict:
        try:
            query = db.session.query(RobCharacter).filter(RobCharacter.tenant_id==tenant_id)
            total = 0
            has_more = False
            if "id" in args and args["id"]:
                query = query.filter(RobCharacter.id==args["id"])
                total = query.count()
                has_more = False
            else:
                if "name" in args and args["name"]:
                    query = query.filter(RobCharacter.name.like(f"%{args['name']}%"))
                if "personality" in args and args["personality"]:
                    query = query.filter(RobCharacter.personality.ilike(f"%{args['descrip']}%"))
                if "timbre_id" in args and args["timbre_id"]:
                    query = query.filter(RobCharacter.default_timbre_id==args["timbre_id"])
                if "emoji_pack_id" in args and args["emoji_pack_id"]:
                    query = query.filter(RobCharacter.default_emoji_pack_id==args["emoji_pack_id"])
                total = query.count()
                if "page" in args and args["page"]>0 and "page_size" in args and args["page_size"]>0:
                    query = query.offset((args['page']-1)*args['page_size']).limit(args['page_size'])
                    has_more = total > args['page']*args['page_size']
            data = query.all()
            return {
                "total": total,
                "has_more": has_more,
                "data": data
            }
        except Exception as e:
            logging.error(e)
            return {
                "total": 0,
                "has_more": False,
                "data": []
            }

        
    @staticmethod
    def create_character(account:AccountWrap,args,ip_addr)->RobCharacter:
        if not account or not isinstance(account,AccountWrap):
            raise NotLoginError()
        tenant_id = account.current_tenant_id
        if "name" not in args or not args["name"]:
            raise CharacterCreateParamError(_("Character name cannot be empty."))
        if "personality" not in args or not args["personality"]:
            raise CharacterCreateParamError(_("Character personality cannot be empty."))
        if "default_timbre_id" not in args or not args["default_timbre_id"]:
            raise CharacterCreateParamError(_("Character default timbre cannot be empty."))
        if "default_emoji_pack_id" not in args or not args["default_emoji_pack_id"]:
            raise CharacterCreateParamError(_("Character default emoji pack cannot be empty."))
        name = args["name"]
        agent_id = args.get("agent_id",None)
        personality = args["personality"]
        price = args.get("price",0)
        if price >0:
            price = int(price*1000)
        config = args.get("config",{})
        appearance_url = args.get("appearance_url",None)
        appearance_file_id = args.get("appearance_file_id",None)
        greet_sentence = args.get("greet_sentence",None)
        wakeup_sentences = args.get("wakeup_sentences",None)
        busy_sentences = args.get("busy_sentences",None)
        stepback_sentences = args.get("stepback_sentences",None)
        default_timbre_id = args.get("default_timbre_id",None)
        default_emoji_pack_id = args.get("default_emoji_pack_id",None)
        try:
            default_timbre = db.session.get(RobTimbre,default_timbre_id)
            if not default_timbre:
                raise TimbreNotExistError(default_timbre_id)
            default_emoji_pack = db.session.get(RobEmojiPack,default_emoji_pack_id)
            if not default_emoji_pack:
                raise EmojiPackageNotExistError(default_emoji_pack_id)
            character = RobCharacter(
                tenant_id = tenant_id, # type:ignore
                name = name, # type:ignore
                agent_id = agent_id, # type:ignore
                personality = personality, # type:ignore
                price = price, # type:ignore
                default_emoji_pack_id = default_emoji_pack_id, # type:ignore
                default_timbre_id = default_timbre_id, # type:ignore
                created_by = account.id, # type:ignore
            )
            if appearance_url:
                character.appearance_url = appearance_url
            if appearance_file_id:
                character.appearance_file_id = appearance_file_id
            if greet_sentence:
                character.greet_sentence = greet_sentence
            if wakeup_sentences:
                character.wakeup_sentences = wakeup_sentences
            if busy_sentences:
                character.busy_sentences = busy_sentences
            if stepback_sentences:
                character.stepback_sentences = stepback_sentences
            db.session.add(character)
            db.session.flush()
            LogService.log(
                tenant_id=tenant_id,
                account_id=account.id,
                action=LogAction.CREATE_CHARACTER,
                content=f"{account.name} create CHARACTER {character.name}:{character.id}",
                created_ip=ip_addr,
                submit=False,
            )
            db.session.commit()
            return character
        except TimbreNotExistError as e:
            db.session.rollback()
            raise e
        except EmojiPackageNotExistError as e:
            db.session.rollback()
            raise e
        except  Exception as e:
            raise CharacterCreateParamError(str(e))

        
    @staticmethod
    def update_character(account:AccountWrap,args,ip_addr)->RobCharacter:
        if not account or not isinstance(account,AccountWrap):
            raise NotLoginError()
        tenant_id = account.current_tenant_id
        if "id" not in args or not args["id"]:
            raise CharacterCreateParamError(_("Character ID is required."))
        if "name" not in args or not args["name"]:
            raise CharacterCreateParamError(_("Character name cannot be empty."))
        if "personality" not in args or not args["personality"]:
            raise CharacterCreateParamError(_("Character personality cannot be empty."))
        if "default_timbre_id" not in args or not args["default_timbre_id"]:
            raise CharacterCreateParamError(_("Character default timbre cannot be empty."))
        if "default_emoji_pack_id" not in args or not args["default_emoji_pack_id"]:
            raise CharacterCreateParamError(_("Character default emoji pack cannot be empty."))
        character_id = args["id"]
        name = args["name"]
        agent_id = args.get("agent_id",None)
        personality = args["personality"]
        price = args.get("price",0)
        if price >0:
            price = int(price*1000)
        
        appearance_url = args.get("appearance_url",None)
        appearance_file_id = args.get("appearance_file_id",None)
        greet_sentence = args.get("greet_sentence",None)
        wakeup_sentences = args.get("wakeup_sentences",None)
        busy_sentences = args.get("busy_sentences",None)
        stepback_sentences = args.get("stepback_sentences",None)
        default_timbre_id = args.get("default_timbre_id",None)
        default_emoji_pack_id = args.get("default_emoji_pack_id",None)
        
        try:

            character = db.session.get(RobCharacter,character_id)
            if not character:
                raise CharacterNotExistError(character_id)
            default_timbre = db.session.get(RobTimbre,default_timbre_id)
            if not default_timbre:
                raise TimbreNotExistError(default_timbre_id)
            
            default_emoji_pack = db.session.get(RobEmojiPack,default_emoji_pack_id)
            if not default_emoji_pack:
                raise EmojiPackageNotExistError(default_emoji_pack_id)
            character.default_timbre_id = default_timbre.id
            character.default_emoji_pack_id = default_emoji_pack.id
            character.name = name
            character.agent_id = agent_id
            character.personality = personality
            character.price = price
            if appearance_file_id:
                character.appearance_file_id = appearance_file_id
            if appearance_url:
                character.appearance_url = appearance_url
            if greet_sentence:
                character.greet_sentence = greet_sentence
            if wakeup_sentences:
                character.wakeup_sentences = wakeup_sentences
            if busy_sentences:
                character.busy_sentences = busy_sentences
            if stepback_sentences:
                character.stepback_sentences = stepback_sentences
            character.updated_at = datetime.now()
            character.updated_by = account.id
            LogService.log(
                tenant_id=tenant_id,
                account_id=account.id,
                action=LogAction.UPDATE_CHARACTER,
                content=f"{account.name} update CHARACTER {character.name}:{character.id}",
                created_ip=ip_addr,
                submit=False,
            )
            db.session.commit()
            return character
        except TimbreNotExistError as e:
            db.session.rollback()
            raise e
        except EmojiPackageNotExistError as e:
            db.session.rollback()
            raise e
        except  Exception as e:
            raise CharacterCreateParamError(str(e))
        
    @staticmethod
    def del_character(account:AccountWrap,character_id,ip_addr):
        character = db.session.get(RobCharacter,character_id)
        if not character:
            raise CharacterNotExistError(character_id)
        try:
            log_msg = f"{account.name} delete Character:{character.id}:{character.name}"
            db.session.delete(character)
            LogService.log(
                account.current_tenant_id,
                account.id,
                LogAction.DEL_CHARACTER,
                log_msg,
                ip_addr,
                submit=False
            )
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            raise e